import { User } from "@/entities/User";
import { initORM } from "@/utils";
import { getRandPassword } from "@/utils/base";
import { sendEmail } from "@/utils/email";
import { createMd5 } from "@/utils/hash";
import { NextApiRequest, NextApiResponse } from "next";
import formidable, { File } from "formidable";
import path from "node:path";
import { getCurrentUser } from "@/services";
import fs from "node:fs";
import { toBase64 } from "@/utils/back";

// !!! this config is required
export const config = {
    api: {
        bodyParser: false,
    },
};

type ProcessedFiles = Array<[string, File]>;
type ProcessedFields = Array<[string, string]>;

async function updateUserProfile(
    req: NextApiRequest,
    res: NextApiResponse<APIRes>
) {
    const uploadDir = path.join(process.cwd(), "./public/uploads");

    /* Get files using formidable */
    const data = await new Promise<
        { files: ProcessedFiles; fields: ProcessedFields } | undefined
    >((resolve, reject) => {
        const form = formidable({
            multiples: false,
            keepExtensions: true,
            uploadDir,
        });

        const files: ProcessedFiles = [];
        const fields: ProcessedFields = [];

        form.on("file", function (field, file) {
            files.push([field, file]);
        });
        form.on("field", function (field, value) {
            fields.push([field, value]);
        });
        form.on("end", () => resolve({ files, fields }));
        form.on("error", (err) => reject(err));
        form.parse(req, () => {
            //
        });
    }).catch((e) => {
        console.log("====upload error", e);
        res.status(500).json({
            success: false,
            data: {},
            message: "Upload error: " + e.message,
        });
    });

    if (!data) {
        res.status(500).json({
            success: false,
            data: {},
            message: "form parse error",
        });

        return;
    }

    const { files, fields } = data;
    const passData = {
        ...Object.fromEntries(fields),
        ...Object.fromEntries(files),
    } as { name: string; password: string; avatar: File };

    const curUser = await getCurrentUser(req);
    let avatarFilename = "";
    if (!curUser) {
        res.status(400).json({
            success: false,
            data: {},
            message: "User not found",
        });
        return;
    }

    const avatarFile = passData.avatar as File;
    let avatarData = "";
    if (avatarFile) {
        avatarFilename =
            createMd5(curUser.email || curUser.name).slice(0, 10) +
            (curUser.avatar?.includes("_A.") ? "_B" : "_A") +
            path.extname(avatarFile.newFilename);

        // output avatar file to dir is meaningless
        const oldPath = path.resolve(uploadDir, avatarFile.newFilename);
        // const newPath = path.resolve(uploadDir, avatarFilename);
        // const ok = fs.renameSync(oldPath, newPath);

        const result = toBase64(oldPath, "image/jpeg");
        if (result.success) {
            avatarData = result.data;
        }
    }

    const avatar = avatarFile ? "/uploads/" + avatarFilename : "";
    const { name, password: pwd } = passData;
    const password = pwd ? createMd5(pwd) : pwd;
    const newData = { name, pass: password, avatar, avatarData };
    const keys = Object.keys(newData) as unknown as Array<keyof typeof newData>;
    keys.forEach((key) => {
        if (newData[key]) {
            if (newData[key]) {
                curUser[key] = newData[key];
            }
        }
    });

    const em = await initORM();
    await em.persistAndFlush(curUser);

    res.status(200).json({
        success: true,
        data: newData,
        message: "update user profile success",
    });

    //   const em = await initORM();
    //   const user = await em.findOne(User, { passResetToken });

    //   if (!user) {
    //     res
    //       .status(400)
    //       .json({ success: false, data: {}, message: "User not found" });
    //     return;
    //   }

    //   user.pass = createMd5(password);
    //   user.passResetToken = "";

    //   await em.persistAndFlush(user);
}

export default async function handler(
    req: NextApiRequest,
    res: NextApiResponse<APIRes>
) {
    if (req.method === "POST") {
        updateUserProfile(req, res);
    } else {
        res.status(405).json({
            success: false,
            data: {},
            message: "Method not allowed",
        });
    }
}
